#pragma once
#include <compl.h>

#include <libapfsds.h>
typedef struct queuenode{
	struct queuenode *next;
	void *val;
}ALIGN(HDEF_CACHE_LINE_BYTES) queuenode_t;

typedef struct{
	queuenode_t *head;
	queuenode_t *tail;
	word_t count;
}ALIGN(HDEF_CACHE_LINE_BYTES) queue_t;


static inline void *queue_init(queue_t *q){
	q->head = NULL;
	q->tail = NULL;
	q->count = 0;
	return q;
}

static inline void queue_push_tail(queue_t *p, queuenode_t *node){
	node->next = NULL;
	if(p->head != NULL){
		p->tail->next = node;
		p->tail = node;
	}
	else{
		p->head = node;
		p->tail = node;
	}
}

static inline queuenode_t *queue_pop_head(queue_t *p){
	queuenode_t *ret = NULL;
	if (p->head) {
		ret = p->head;
		p->head = p->head->next;
		if(!p->head){
			p->tail = NULL;
		}
	}
	return ret;
}

word_t queue_push_tail_cb (APFSDS_ARGLIST){
	PARAM_USED(arg2, arg3);
	if((arg0 != 0) && (arg1 != 0))
		queue_push_tail((queue_t *)arg0,(queuenode_t *)arg1);
	return (++((queue_t *)arg0)->count);
}

word_t queue_pop_head_cb (APFSDS_ARGLIST){
	PARAM_USED(arg1, arg2, arg3);
	void *ret = NULL;
	if(arg0 != 0)
		ret = queue_pop_head((queue_t *)arg0);
	return (word_t)ret;
}